package media

import (
    "context"
    "fmt"
    "net"
	"sync"
	"bytes"
	"strings"
    //"time"
    //"os/exec"
    //"path/filepath"
	"net/http"
    "os"
    "encoding/binary"
	rtmpLib "github.com/deepch/vdk/format/rtmp"
    "github.com/pion/rtp"
    //"github.com/pion/webrtc/v3/pkg/media/h264reader"

    "github.com/deepch/vdk/av"
    "github.com/deepch/vdk/format/flv"
	"github.com/deepch/vdk/codec/h264parser"
    //"github.com/deepch/vdk/format/flv/flvio"
    // "github.com/pion/rtp"
    // "github.com/pion/rtp/codecs"
)

// h264Buffers 存储每个设备或流的 H.264 数据缓冲区
var h264Buffers = make(map[string][]byte)
var bufferMutex sync.RWMutex

var (
	rtpBuffers = make(map[string]*RTPPacketBuffer) // 存储每个设备的RTP缓冲区
	bufferMux  sync.RWMutex                       // 保护rtpBuffers的读写
)

// RTPPacketBuffer 用于存储RTP数据包
type RTPPacketBuffer struct {
	packets []rtp.Packet
	mu      sync.Mutex
}

const maxBufferSize = 1024 * 1024 // 1MB 最大内存缓冲

var muxers = make(map[string]*flv.Muxer)
var muxerMutex sync.RWMutex
//var rtspServer   *RTSPServer

// NewRTPPacketBuffer 创建一个新的RTPPacketBuffer
func NewRTPPacketBuffer() *RTPPacketBuffer {
	return &RTPPacketBuffer{
		packets: make([]rtp.Packet, 0),
	}
}

// AddPacket 添加RTP数据包到缓冲区
func (b *RTPPacketBuffer) AddPacket(packet rtp.Packet) {
	b.mu.Lock()
	defer b.mu.Unlock()
	b.packets = append(b.packets, packet)
}

// Clear 清空缓冲区
func (b *RTPPacketBuffer) Clear() {
	b.mu.Lock()
	defer b.mu.Unlock()
	b.packets = make([]rtp.Packet, 0)
}

// startRTPServer 启动 RTP 服务器
func StartRTPServerD(deviceID string, ctx context.Context) {
    rtpAddr, err := net.ResolveUDPAddr("udp", "192.168.1.213:15060") // RTP 默认端口
    if err != nil {
        fmt.Printf("Failed to resolve RTP address: %v\n", err)
        return
    }

    rtpConn, err := net.ListenUDP("udp", rtpAddr)
    if err != nil {
        fmt.Printf("Failed to start RTP server: %v\n", err)
        return
    }
    defer rtpConn.Close()

	fmt.Println("Listening for RTP packets on UDP port 15060 ")

	// 创建H.264文件
	// file, err := os.Create("output.h264")
	// if err != nil {
	// 	fmt.Println("Error creating H.264 file:", err)
	// 	return
	// }
	// defer file.Close()

	buffer := make([]byte, 1500) // 通常MTU为1500字节

    go startFFMPEG(deviceID)

	for {
        select {
        case <-ctx.Done():
            fmt.Printf("RTP server for device %s is stopping...\n", deviceID)
            return
        default:
            // 读取UDP数据包
            n, _, err := rtpConn.ReadFromUDP(buffer)
            if err != nil {
                fmt.Println("Error reading from UDP:", err)
                continue
            }

            // 解析RTP头部
            if n < 12 {
                fmt.Println("Invalid RTP packet: too short")
                continue
            }

            // RTP头部解析
            //version := buffer[0] >> 6
            //padding := (buffer[0] >> 5) & 0x1
            extension := (buffer[0] >> 4) & 0x1
            csrcCount := buffer[0] & 0x0F
            //marker := buffer[1] >> 7
            //payloadType := buffer[1] & 0x7F
            //sequenceNumber := binary.BigEndian.Uint16(buffer[2:4])
            //timestamp := binary.BigEndian.Uint32(buffer[4:8])
            //ssrc := binary.BigEndian.Uint32(buffer[8:12])

            //fmt.Printf("RTP Packet: Version=%d, Padding=%d, Extension=%d, CSRC Count=%d, Marker=%d, Payload Type=%d, Sequence Number=%d, Timestamp=%d, SSRC=%d\n",
            //    version, padding, extension, csrcCount, marker, payloadType, sequenceNumber, timestamp, ssrc)

            // 提取H.264负载
            payloadStart := 12 + int(csrcCount)*4
            if extension == 1 {
                extensionLength := int(binary.BigEndian.Uint16(buffer[payloadStart+2 : payloadStart+4]))
                payloadStart += 4 + extensionLength*4
            }

            if payloadStart >= n {
                fmt.Println("Invalid RTP packet: payload start beyond packet length")
                continue
            }

            payload := buffer[payloadStart:n]
            
            h264Buffers[deviceID] =  payload
            //h264Buffers[deviceID] = payload
            pushH264Data(deviceID,payload)

            //写入H.264文件
            // _, err = file.Write(payload)
            // if err != nil {
            //     fmt.Println("Error writing to H.264 file:", err)
            //     continue
            // }
        }
	}
}

// startRTPServer 启动 RTP 服务器
// func StartRTPServer(deviceID string, ctx context.Context) {
//     rtpAddr, err := net.ResolveUDPAddr("udp", "192.168.1.213:15060") // RTP 默认端口
//     if err != nil {
//         fmt.Printf("Failed to resolve RTP address: %v\n", err)
//         return
//     }

//     rtpConn, err := net.ListenUDP("udp", rtpAddr)
//     if err != nil {
//         fmt.Printf("Failed to start RTP server: %v\n", err)
//         return
//     }
//     defer rtpConn.Close()

//     fmt.Printf("RTP server started for device %s on %s\n", deviceID, rtpAddr.String())

// 	// 1. 初始化RTSP服务器
// 	//go StartRTSP()
//     // 2. 启动推流
//     //go startFFMPEG(deviceID)
	
//     buf := make([]byte, 1500) // RTP 数据包最大长度
//     for {
//         select {
//         case <-ctx.Done():
//             fmt.Printf("RTP server for device %s is stopping...\n", deviceID)
//             return
//         default:
//             n, addr, err := rtpConn.ReadFromUDP(buf)
//             if err != nil {
//                 if neterr, ok := err.(net.Error); ok && neterr.Temporary() {
//                     continue
//                 }
//                 fmt.Printf("Failed to read %s RTP data: %v %d\n",addr, err , n)
//                 return
//             }
//             //fmt.Printf("Received RTP data from %s: %d bytes\n", addr.String(), n)
//             // 这里可以添加对 RTP 数据包的处理逻辑
//             var rtpPacket rtp.Packet
//             err = rtpPacket.Unmarshal(buf[:n])
//             if err != nil {
//                 fmt.Println("Error unmarshaling RTP packet:", err)
//                 continue
//             }

//             //handleRTPPacket(deviceID, rtpPacket)
//         }
//     }
// }

// 将数据写入 H.264 文件的函数
func writeToH264File(deviceID string, data []byte) {
    // 构建文件路径，以设备 ID 命名
    filePath := fmt.Sprintf("%s.h264", deviceID)
    // 以追加、创建和只写模式打开文件
    file, err := os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
    if err != nil {
        fmt.Println("Error opening file:", err)
        return
    }
    // 确保文件在函数结束时关闭
    defer file.Close()

    // 将数据写入文件
    _, err = file.Write(data)
    if err != nil {
        fmt.Println("Error writing to file:", err)
        return
    }
    fmt.Printf("Data written to %s\n", filePath)
}


// func handleH264(deviceID string, payload []byte) {
//     bufferMutex.Lock()
//     defer bufferMutex.Unlock()

//     // 检查数据是否包含起始码
//     if len(payload) >= 4 && payload[0] == 0x00 && payload[1] == 0x00 && payload[2] == 0x00 && payload[3] == 0x01 {
//         // 数据已经包含起始码，直接处理
//         // 这里保持原有的处理逻辑
//         reader := bytes.NewReader(payload)
//         h264Reader, err := h264bitstream.NewReader(reader)
//         if err != nil {
//             fmt.Println("Error creating H.264 reader:", err)
//             return
//         }

//         for {
//             _, err := h264Reader.NextNAL()
//             if err != nil {
//                 break
//             }
//         }

//         h264Buffers[deviceID] = append(h264Buffers[deviceID], payload...)
//         pushH264Data(deviceID)
//     } else {
//         // 数据不包含起始码，尝试添加
//         newPayload := make([]byte, len(payload)+4)
//         copy(newPayload[:4], []byte{0x00, 0x00, 0x00, 0x01})
//         copy(newPayload[4:], payload)

//         reader := bytes.NewReader(newPayload)
//         h264Reader, err := h264bitstream.NewReader(reader)
//         if err != nil {
//             fmt.Println("Error creating H.264 reader:", err)
//             return
//         }

//         for {
//             _, err := h264Reader.NextNAL()
//             if err != nil {
//                 break
//             }
//         }

//         h264Buffers[deviceID] = append(h264Buffers[deviceID], newPayload...)
//         pushH264Data(deviceID)
//     }
// }

// func handleH264(deviceID string, payload []byte) {
//     bufferMutex.Lock()
//     defer bufferMutex.Unlock()

//     // 获取 NALU 类型
//     nalType := payload[0] & 0x1F

//     var nalUnit []byte
//     switch {
//     case nalType >= 1 && nalType <= 23:
//         // 单 NALU 单元
//         nalUnit = append([]byte{0x00, 0x00, 0x00, 0x01}, payload...)
//     case nalType == 28: // FU-A (Fragmentation Unit A)
//         // 分片的 NALU
//         fuIndicator := payload[0]
//         fuHeader := payload[1]
//         startBit := (fuHeader & 0x80) != 0
//         endBit := (fuHeader & 0x40) != 0
//         nalTypeInFu := fuHeader & 0x1F

//         if startBit {
//             // 开始分片，创建新的 NALU 缓存
//             fragmentedNALUs[deviceID] = []byte{0x00, 0x00, 0x00, 0x01, (fuIndicator & 0xE0) | nalTypeInFu}
//         }

//         if len(fragmentedNALUs[deviceID]) > 0 {
//             // 追加分片数据
//             fragmentedNALUs[deviceID] = append(fragmentedNALUs[deviceID], payload[2:]...)
//         }

//         if endBit {
//             // 结束分片，完成 NALU 组装
//             nalUnit = fragmentedNALUs[deviceID]
//             delete(fragmentedNALUs, deviceID)
//         }
//     case nalType == 24: // STAP-A
//         offset := 1 // 跳过 STAP-A 头
//         for offset < len(payload) {
//             if offset+2 > len(payload) {
//                 fmt.Printf("Error: Insufficient data to read NALU length in STAP-A for device %s\n", deviceID)
//                 break
//             }
//             // 读取 NALU 长度
//             naluLength := (int(payload[offset]) << 8) | int(payload[offset+1])
//             offset += 2

//             if offset+naluLength > len(payload) {
//                 fmt.Printf("Error: NALU length exceeds remaining payload in STAP-A for device %s\n", deviceID)
//                 break
//             }
//             // 提取 NALU
//             nalu := payload[offset : offset+naluLength]
//             offset += naluLength

//             // 递归处理每个子 NALU
//             handleH264(deviceID, nalu)
//         }
//     case nalType == 25: // STAP-B，简单处理，类似 STAP-A，忽略扩展部分
//         offset := 1 // 跳过 STAP-B 头
//         for offset < len(payload) {
//             if offset+2 > len(payload) {
//                 fmt.Printf("Error: Insufficient data to read NALU length in STAP-B for device %s\n", deviceID)
//                 break
//             }
//             // 读取 NALU 长度
//             naluLength := (int(payload[offset]) << 8) | int(payload[offset+1])
//             offset += 2

//             if offset+naluLength > len(payload) {
//                 fmt.Printf("Error: NALU length exceeds remaining payload in STAP-B for device %s\n", deviceID)
//                 break
//             }
//             // 提取 NALU
//             nalu := payload[offset : offset+naluLength]
//             offset += naluLength

//             // 递归处理每个子 NALU
//             handleH264(deviceID, nalu)
//         }
//     case nalType == 30: // MTAP16
//         // 简单处理，这里假设先不解析时间偏移，直接提取子 NALU
//         offset := 1 // 跳过 MTAP16 头
//         for offset < len(payload) {
//             if offset+2 > len(payload) {
//                 fmt.Printf("Error: Insufficient data to read NALU length in MTAP16 for device %s\n", deviceID)
//                 break
//             }
//             // 读取 NALU 长度（假设长度占 2 字节，实际可能更复杂）
//             naluLength := (int(payload[offset]) << 8) | int(payload[offset+1])
//             offset += 2

//             if offset+naluLength > len(payload) {
//                 fmt.Printf("Error: NALU length exceeds remaining payload in MTAP16 for device %s\n", deviceID)
//                 break
//             }
//             // 提取 NALU
//             nalu := payload[offset : offset+naluLength]
//             offset += naluLength

//             // 递归处理每个子 NALU
//             handleH264(deviceID, nalu)
//         }
//     case nalType == 31: // MTAP24
//         // 简单处理，这里假设先不解析时间偏移，直接提取子 NALU
//         offset := 1 // 跳过 MTAP24 头
//         for offset < len(payload) {
//             if offset+3 > len(payload) {
//                 fmt.Printf("Error: Insufficient data to read NALU length in MTAP24 for device %s\n", deviceID)
//                 break
//             }
//             // 读取 NALU 长度（假设长度占 3 字节，实际可能更复杂）
//             naluLength := (int(payload[offset]) << 16) | (int(payload[offset+1]) << 8) | int(payload[offset+2])
//             offset += 3

//             if offset+naluLength > len(payload) {
//                 fmt.Printf("Error: NALU length exceeds remaining payload in MTAP24 for device %s\n", deviceID)
//                 break
//             }
//             // 提取 NALU
//             nalu := payload[offset : offset+naluLength]
//             offset += naluLength

//             // 递归处理每个子 NALU
//             handleH264(deviceID, nalu)
//         }
//     case nalType == 0:
//         // 保留类型，记录日志并忽略
//         fmt.Printf("Received reserved NALU type 0, ignoring...\n")
//     default:
//         fmt.Printf("Unsupported NALU type: %d\n", nalType)
//         return
//     }

//     if len(h264Buffers[deviceID])+len(nalUnit) > maxBufferSize {
//         // 缓冲区已满，清空缓冲区或处理旧数据
//         h264Buffers[deviceID] = nil
//     }

//     if len(nalUnit) > 0 {
//         // 追加 NALU 到缓冲区
//         h264Buffers[deviceID] = append(h264Buffers[deviceID], nalUnit...)
//         // 推送 H.264 数据到 FFmpeg
//         pushH264Data(deviceID)
//     }
// }

func handleAudio(payload []byte) {
    fmt.Println("Handling audio stream...")
}

//RTMP

func extractDeviceIDFromRTMPURL(url string) (string, error) {
    // 解析RTMP URL，假设设备ID是URL中最后一个部分
    parts := strings.Split(url, "/")
    if len(parts) < 2 {
        return "", fmt.Errorf("invalid RTMP URL")
    }
    return parts[len(parts)-1], nil
}

// H264ToFLV 将 H.264 数据转换为 FLV 格式的字节数据
func H264ToFLV(h264Data []byte) ([]byte, error) {
    // 创建一个 bytes.Buffer 用于存储 FLV 数据
    var flvBuffer bytes.Buffer

    // 创建一个 Muxer 实例，将其关联到 bytes.Buffer
    muxer := flv.NewMuxer(&flvBuffer)

    // 创建 H.264 编解码数据
    h264CodecData, err := h264parser.NewCodecDataFromAVCDecoderConfRecord(h264Data)
    if err != nil {
        return nil, fmt.Errorf("Error creating H.264 codec data: %w", err)
    }

    // 定义音视频流信息
    streams := []av.CodecData{h264CodecData}

    // 写入文件头和视频流信息
    err = muxer.WriteHeader(streams)
    if err != nil {
        return nil, fmt.Errorf("Error writing FLV header: %w", err)
    }

    // 创建一个 av.Packet 结构体来封装 H.264 数据
    pkt := av.Packet{
        Idx:       0, // 视频流索引
        Time:      0, // 时间戳
        Data:      h264Data,
        IsKeyFrame: true, // 假设是关键帧
    }

    // 写入 H.264 数据
    err = muxer.WritePacket(pkt)
    if err != nil {
        return nil, fmt.Errorf("Error writing H.264 packet: %w", err)
    }

    // 写入文件尾部信息
    err = muxer.WriteTrailer()
    if err != nil {
        return nil, fmt.Errorf("Error writing FLV trailer: %w", err)
    }

    // 返回 FLV 格式的字节数据
    return flvBuffer.Bytes(), nil
}

func handlePublish(conn *rtmpLib.Conn) {
    fmt.Println("Publish connection received")
    // 在这里处理推流连接的逻辑，例如获取推流的流信息等
}

func handlePlay(conn *rtmpLib.Conn) {

    fmt.Println("Publish connection received")
    // 假设从客户端请求中获取设备 ID，这里简单模拟
    deviceID := "34020000001320000001"

	// 获取客户端请求的RTMP地址
	rtmpURL := conn.URL

	// 解析RTMP地址，提取设备ID
	deviceID, err := extractDeviceIDFromRTMPURL(rtmpURL.String())
	if err != nil {
		fmt.Printf("Error extracting device ID: %v\n", err)
		// 根据实际情况进行错误处理，比如返回错误信息给客户端
		return
	}

	for {
		// 加读锁，确保并发安全
		bufferMutex.RLock()
		h264Data := h264Buffers[deviceID]
		bufferMutex.RUnlock()

		if len(h264Data) > 0 {
			// 首先，需要准备 RTMP 连接以进行写入操作
			if err := conn.Prepare(); err != nil {
				fmt.Printf("Error preparing RTMP connection: %v\n", err)
				return
			}

			// 将 H.264 数据转换为 FLV 格式
			flvData, err := H264ToFLV(h264Data)
			if err != nil {
				fmt.Printf("Error converting H.264 to FLV: %v\n", err)
				return
			}

			// 创建一个 av.Packet 结构体来封装 FLV 数据
			pkt := av.Packet{
				Idx:    0, // 假设视频流索引为 0
				Time:   0, // 时间戳，可根据实际情况调整
				Data:   flvData,
				IsKeyFrame:  true, // 假设是关键帧，可根据实际情况调整
			}

			// 发送数据包
			if err := conn.WritePacket(pkt); err != nil {
				fmt.Printf("Error sending FLV data for device %s: %v\n", deviceID, err)
			} else {
				fmt.Printf("Sent %d bytes of FLV data to client for device %s\n", len(flvData), deviceID)
			}

			// 清空缓冲区
			bufferMutex.Lock()
			h264Buffers[deviceID] = nil
			bufferMutex.Unlock()
		}
	}
}



func handleConn(conn *rtmpLib.Conn) {
	fmt.Println("New connection received")

    // 记录连接信息
    fmt.Printf("Client connected from %s \n", conn.NetConn().RemoteAddr())

    // 调用默认的连接处理逻辑
	if err := conn.Prepare(); err != nil {
		fmt.Printf("Error preparing connection: %v\n", err)
		conn.Close()
		return
	}

	go handlePlay(conn)

	// 简单的认证逻辑，这里可以根据实际需求修改
    // 例如，检查客户端的 IP 地址、请求的 URL 等
    // rtmpURL := conn.URL
    // if rtmpURL == nil {
    //     fmt.Println("Invalid RTMP URL in connection")
    //     conn.Close()
    //     return
    // }

}

func convertToRTMP() {

	server := &rtmpLib.Server{
        Addr:          ":1935", // 设置服务器监听的地址和端口，这里使用默认的 RTMP 端口 1935
        HandlePublish: handlePublish,
        HandlePlay:    handlePlay,
        HandleConn:    handleConn,
    }

    fmt.Println("Starting RTMP server...")
    if err := server.ListenAndServe(); err != nil {
        fmt.Errorf("Failed to start RTMP server: %v", err)
    }

}

//HTTP
// func handleHTTPPlay(w http.ResponseWriter, r *http.Request) {
//     fmt.Println("Play connection received")
//     // 打开本地的音视频文件
//     // file, err := os.Open("path/to/your/video.mp4")
//     // if err != nil {
//     //     http.Error(w, "Failed to open file", http.StatusInternalServerError)
//     //     return
//     // }
//     // defer file.Close()

//     // // 设置响应头，指定内容类型为 MP4 视频
//     // w.Header().Set("Content-Type", "video/mp4")

//     // // 将文件内容复制到响应中发送给客户端
//     // _, err = io.Copy(w, file)
//     // if err != nil {
//     //     http.Error(w, "Failed to send file", http.StatusInternalServerError)
//     //     return
//     // }
// }

// func convertToHTTP() {
    
// 	// 注册处理函数，当客户端请求 /stream 路径时，调用 handlePlay 函数
// 	http.HandleFunc("/stream", handleHTTPPlay)

// 	// 启动 HTTP 服务器，监听 8080 端口
// 	fmt.Println("Starting HTTP server on :15062")
// 	http.ListenAndServe(":15062", nil)
	
// }

func handleClientRequest(w http.ResponseWriter, r *http.Request) {
    streamType := r.URL.Query().Get("streamType")
    if streamType == "rtmp" {
        fmt.Fprintf(w, "RTMP stream URL: rtmp://your-server:1935/live/stream")
    } else if streamType == "http" {
        fmt.Fprintf(w, "HTTP stream URL: http://your-server:15062/stream")
    } else {
        fmt.Fprintf(w, "Invalid stream type")
    }
}